#include "StdAfx.h"
#include "GrassLoaderDemoState.h"

#include "CoreEngine.h"
#include "MainState.h"

#include <sstream>

namespace
{
	template <typename T> std::string ToString(const T& t)
	{
		std::ostringstream os;
		os << t;
		return os.str();
	};
}

GrassLoaderDemoState::GrassLoaderDemoState()
	: FEApplication(), FEngine::KeyboardInputListener(), FEngine::MouseInputListener()
{
	mCameraHandler			= NULL;
	mStatPanel				= NULL;
	mGrassLoader			= NULL;
	mGrassBillboardNode		= NULL;
	mBillboardTexture		= NULL;
	mShowLoader				= true;
}

GrassLoaderDemoState::~GrassLoaderDemoState()
{
	FEngine::InputManager::getInstance()->unregisterKeyboardInputListener(this);
	FEngine::InputManager::getInstance()->unregisterMouseInputListener(this);
	
	delete mCameraHandler;
	delete mStatPanel;
	if (mGrassLoader)
		delete mGrassLoader;

	for (std::list<FEngine::Billboard*>::iterator it = mListBillboard.begin(); it != mListBillboard.end(); ++it)
		delete *it;

	if (mGrassBillboardNode)
		delete mGrassBillboardNode;
	
	for (std::list<FEngine::TextLabel*>::iterator it = mListLabels.begin(); it != mListLabels.end(); ++it)
		delete *it;

	if (mLabelNumberObject)
		delete mLabelNumberObject;
	if (mLabelTypeObject)
		delete mLabelTypeObject;

	if (mBillboardTexture)
		mBillboardTexture->Release();
	if (mGround)
		delete mGround;
}

void GrassLoaderDemoState::initialize()
{
	FEngine::FEApplication::initialize();
	FEngine::InputManager::getInstance()->registerKeyboardInputListener(this);
	FEngine::InputManager::getInstance()->registerMouseInputListener(this);
	
	FEngine::CoreEngine::getInstance()->getCamera()->setFarDistanceView(500.0f);

	mCameraHandler = new FEngine::FreeCameraHandler(FEngine::CoreEngine::getInstance()->getCamera(), Vector3(0, 3, -50), Vector3(0, 0, 1));
	addChild(mCameraHandler);
	
	FEngine::CoreEngine::getInstance()->disableFog();
	
	FEngine::CoreEngine::getInstance()->setSkyDome("skydome1.dds", 1.0f);

	mStatPanel = new StatPanel();
	addGUIElement(mStatPanel);

	
	mListLabels.push_back(new FEngine::TextLabel("This show how the GrassLoader works", 350, 10, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());
	mListLabels.push_back(new FEngine::TextLabel("The GrassLoader handle the creation and management of billboards", 350, 40, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());
	mListLabels.push_back(new FEngine::TextLabel("Press SPACE to switch between the GrassLoader and standard billboards", 350, 70, 0, 200, 22, FEngine::ColorRGB(255, 255, 255)));
	addGUIElement(mListLabels.back());
	
	// Create the grass loader
	Vector2 area(500, 500);
	float blockSize = 30.0f;
	mGrassLoader = new FEngine::GrassLoader(blockSize, 95.0f);
	mGrassLoader->createBillboard("largegrass.png");
	Vector3 posPrim;
	for (int i = (int)-area.x / 2; i < area.x / 2; i += 2)
	{
		for (int j = (int)-area.y / 2; j < area.y / 2; j += 2)
		{
			posPrim = Vector3((float)(rand() % 10) / 10.0f - 5.0f, 0, (float)(rand() % 10) / 10.0f - 5.0f); // -5 / 5
			posPrim += Vector3((float)i, 0, (float)j);
			float scale = (float)(rand() % 4) / 10.0f + 0.8f;

			mGrassLoader->addBillboard(posPrim, Vector3(2.0f, scale, 1.0f), 0.3f, (float)(rand() % 6));
		}
	}
	mGrassLoader->calculateStats();

	// Create the billboards
	
	// Load the texture one time
	if (D3DXCreateTextureFromFileEx(FEngine::CoreEngine::getInstance()->getDeviceInterface(), L"largegrass.png", D3DX_DEFAULT, D3DX_DEFAULT, 
								D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, 
								NULL, NULL, &mBillboardTexture) != D3D_OK)
		throw FEngine::FEngineException("GrassLoaderDemoState", "initialize", "Cannot load the texture file");


	area = Vector2(100, 100);
	FEngine::Billboard* bill;
	mGrassBillboardNode = new FEngine::Node();
	for (int i = (int)-area.x / 2; i < area.x / 2; i += 2)
	{
		for (int j = (int)-area.y / 2; j < area.y / 2; j += 2)
		{
			Vector3 posPrim = Vector3((float)(rand() % 10) / 10.0f - 5.0f, 0, (float)(rand() % 10) / 10.0f - 5.0f);
			posPrim += Vector3((float)i, 0, (float)j);
			float scale = (float)(rand() % 4) / 10.0f + 0.8f;

			bill = new FEngine::Billboard(posPrim, Vector3(2.0f, scale, 1.0f), mBillboardTexture, 0.3f, (float)(rand() % 6));
			mGrassBillboardNode->addChild(bill);
			mListBillboard.push_back(bill);
		}
	}

	
	// Create the ground
	mGround = new FEngine::PrimitiveCube(1000.0f);
	addChild(mGround);
	mGround->translate(0, -1000.0f, 0);
	mGround->setColor(20, 50, 20);
	
	if (!mShowLoader)
		addChild(mGrassBillboardNode);
	
	mLabelTypeObject = new FEngine::TextLabel("GrassLoader", 20, 200, 100, 30, 22, FEngine::ColorRGB(255, 255, 255));
	addGUIElement(mLabelTypeObject);
	mLabelNumberObject = new FEngine::TextLabel("Number of object :", 10, 240, 100, 30, 22, FEngine::ColorRGB(255, 255, 255));
	addGUIElement(mLabelNumberObject);
}

void GrassLoaderDemoState::update(double _elapsedTime)
{
	FEApplication::update(_elapsedTime);

	if (mShowLoader)
		mGrassLoader->update(_elapsedTime);
}

void GrassLoaderDemoState::updateGUI(double _elapsedTime)
{
	FEApplication::updateGUI(_elapsedTime);

	
	if (mShowLoader)
	{
		mLabelTypeObject->setText("GrassLoader");
		mLabelNumberObject->setText("Number of object (visible / total) : " + ToString(mGrassLoader->getNumberVisibleObject()) + " / " + ToString(mGrassLoader->getNumberObject()));
	}
	else
	{
		mLabelTypeObject->setText("Billboards");
		mLabelNumberObject->setText("Number of object : " + ToString(mListBillboard.size()));
	}
}


void GrassLoaderDemoState::render(double _elapsedTime)
{
	FEApplication::render(_elapsedTime);

	if (mShowLoader)
		mGrassLoader->render(_elapsedTime);
}

void GrassLoaderDemoState::keyPressed(int _key)
{
	if (_key == FEngine::InputManager::KEY_SPACE)
	{
		mShowLoader = !mShowLoader;

		if (mShowLoader)
			removeChild(mGrassBillboardNode);
		else
			addChild(mGrassBillboardNode);
	}

	if (_key == FEngine::InputManager::KEY_ESCAPE)
	{
		MainState* newApp = new MainState();
		FEngine::CoreEngine::getInstance()->setApplication(newApp);
	}
}

void GrassLoaderDemoState::keyReleased(int _key)
{
}

void GrassLoaderDemoState::mouseButtonPressed(int _button, const Vector2& _position)
{
}

void GrassLoaderDemoState::mouseButtonReleased(int _button, const Vector2& _position)
{
}

void GrassLoaderDemoState::mouseMoved(const Vector2& _delta)
{
}
